-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[qualifier] DSS0210,A2-7-2,7 validate authentication for subscription CRUD+search endpoints #514
Conversation
94b6ff4
to
cf20b6c
Compare
de0fc97
to
9f0fbfa
Compare
ec7fc27
to
57e5057
Compare
Taking to draft to include some refactors that are needed to support the other entities |
54fd720
to
ae48aee
Compare
Overall structure is now stable: the other entities will be added to the scenario in a way that is similar to how the subscription endpoints are tested. |
b1ea57a
to
e8224fd
Compare
e8224fd
to
23b3548
Compare
05ce68e
to
e3e8674
Compare
monitoring/uss_qualifier/scenarios/astm/utm/dss/authentication/authentication_validation.py
Show resolved
Hide resolved
monitoring/uss_qualifier/scenarios/astm/utm/dss/authentication/generic.py
Outdated
Show resolved
Hide resolved
88d491d
to
4daa94f
Compare
4daa94f
to
f126f26
Compare
f126f26
to
0361a96
Compare
Rebased on top of master: should be ready for review. |
0361a96
to
6266dd6
Compare
""" | ||
super().__init__() | ||
scopes = {Scope.StrategicCoordination: "create and delete subscriptions"} | ||
# We use the AvailabilityArbitration scope as the 'wrong' scope for some tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of necessarily using AvailabilityArbitration, we could just pick a scope that's authorized and not the correct one. I'd probably add a list_authorized_scopes() method to DSSInstanceResource that returns the values in its self._auth_adapter.scopes, then pick one of those that isn't the correct scope and isn't a blank scope (if such an option exists).
monitoring/uss_qualifier/scenarios/astm/utm/dss/authentication/generic.py
Show resolved
Hide resolved
monitoring/uss_qualifier/scenarios/astm/utm/dss/authentication/generic.py
Outdated
Show resolved
Hide resolved
""" | ||
q = fetch.query_and_describe( | ||
client=self._invalid_token_session, | ||
scope=Scope.StrategicCoordination, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scope=Scope.StrategicCoordination, | |
scope=self._valid_scope, |
|
||
This scenario will check for the scope's availability and transparently ignore checks that can't be conducted. | ||
|
||
The scopes the scenario is expected to be allowed to use are: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: It's probably worth clarifying which scopes are mandatory (just utm.strategic_coordination, I think) and which will provide additional test coverage
""" | ||
A scenario that verifies that the DSS properly authenticates requests to all its endpoints. | ||
|
||
This scenario does not (yet) cover anything related to authorization: this first version |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand the distinction wrt authorization -- A2.7.2(7) mentions "authorization" rather than authentication and it seems like we're covering authorization here (e.g., reject for incorrect scope). I would expect authentication in the DSS scope to be mostly limited to checking the signature of the access token, though authentication is one portion of authorization (DSS should generally not authorized unauthenticated users, for instance)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is meant to convey that the scenario is not checking situations where a client that does not own an entity tries to mutate or delete it.
Indeed, checking for scopes is already a step towards authorization checks, and I will reword the comment:
Note that although the wording for A2.7.2(7) contains authorization, I did not interpret it as meaning we need to check all authorization scenarios:
Tests must demonstrate that access to the interfaces is denied when a properly formed authorization with an appropriate authorization scope is not provided.
Here the authorization is something that must be provided by the client (in my assumption), so I interpret that the specification uses that word to refer to the token, not to something that the DSS needs to do. (Authorization checks are or will be properly covered by other scenarios, so an inaccurate interpretation here should have no impact on overall coverage)
4105db5
to
681545a
Compare
681545a
to
2464516
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good following these comments
# For the 'wrong' scope we pick anything from the available scopes that isn't the SCD or empty scope: | ||
available_scopes = dss.get_authorized_scopes() | ||
available_scopes.remove(Scope.StrategicCoordination) | ||
available_scopes.remove("") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will throw a KeyError if the empty string is not present in available_scopes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced .remove
with discard
scopes = {Scope.StrategicCoordination: "create and delete subscriptions"} | ||
# For the 'wrong' scope we pick anything from the available scopes that isn't the SCD or empty scope: | ||
available_scopes = dss.get_authorized_scopes() | ||
available_scopes.remove(Scope.StrategicCoordination) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will throw a KeyError if the scope isn't in available_scopes. We haven't yet made the call to get_instance
, so we don't yet know if this scope is actually available or not. After calling get_instance
, either we'll have a working DSSInstance and can be confident the required scopes are available, or else a MissingResourceError would have aborted execution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, indeed. get_instance
is now called at the earliest possible time in the constructor.
2464516
to
e6b6f51
Compare
e6b6f51
to
6c6b032
Compare
available_scopes.discard("") | ||
|
||
self._wrong_scope = ( | ||
random.choice(list(available_scopes)) if available_scopes else None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, we want automated tests to be repeatable. Pseudorandomness is ok, but we should generally initialize any pseudorandom generator with a fixed seed so test results are repeatable. In this case, we probably shouldn't pick an item randomly, but instead select whatever item is "first".
scopes = {Scope.StrategicCoordination: "create and delete subscriptions"} | ||
# Note: .get_instance needs to be called before .get_authorized_scopes to | ||
# guarantee that the returned scopes are available for use. | ||
self._dss = dss.get_instance(scopes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line indicates that self._dss
will only ever make calls with scopes
, which only contains StrategicCoordination at this point. It seems like we should wait to call this until we know what scopes we want to use (i.e., ~line 84)
random.choice(list(available_scopes)) if available_scopes else None | ||
) | ||
if self._wrong_scope: | ||
scopes[ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not doing anything here because scopes
was already used above to get_instance
. get_instance
should be called after we have figured out all our scopes
.
""" | ||
super().__init__() | ||
scopes = {Scope.StrategicCoordination: "create and delete subscriptions"} | ||
# Note: .get_instance needs to be called before .get_authorized_scopes to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_authorized_scopes
can be called any time (no need to call get_instance
first), and we want to use it to figure out what scopes we need in order to be able to call get_instance
with the appropriate information.
Implement comments
6c6b032
to
43569ae
Compare
Adds a scenario to begin validating the DSS0210,A2-7-2,7 requirements:
(The gist of it is that each DSS endpoint should properly check the presence of valid credentials).
This covers the subscription related endpoints (CRUD + search) for the following situations:
The other endpoints will be covered in upcoming PRs